package com.csj.cloud.core.utils;

import com.csj.cloud.common.entity.User;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * @Author:ChengshaoJie
 * @Description: 这比直接new Thread来处理的好处是能在60秒内重用已创建的线程
 *        当池子大小等于corePoolSize，把请求放入workQueue中，池子里的空闲线程就去从workQueue中取任务并处理
 *        当workQueue放不下新入的任务时，新建线程入池，并处理请求，如果池子大小撑到了maximumPoolSize就用RejectedExecutionHandler来做拒绝处理
 *        另外，当池子的线程数大于corePoolSize的时候，多余的线程会等待keepAliveTime长的时间，如果无请求可处理就自行销毁
 *        使用无界队列，要防止任务增长的速度远远超过处理任务的速度，控制不好可能导致的结果就是内存溢出。
 *        使用有界队列，关键在于调节线程数和Queue大小 ，线程数多，队列容量少，资源浪费。线程数少，队列容量多，性能低，还可能导致内存溢出。
 * @Date:Created in 上午 9:49 2019/11/29 0029
 */
public class ThreadUtil {
    static final int nThreads = Runtime.getRuntime().availableProcessors();
    public void test(){
//      当前是计算型。IO密集型，不占用cpu，可以设置线程大一点，提高利用率。
        ExecutorService executors = Executors.newFixedThreadPool(nThreads+1);
        List<Future<User>> list = new ArrayList<>();
        for (int i=0;i<20;i++){
            list.add(executors.submit(new InnerA(i)));
        }
        for (int i=0;i<list.size();i++){
            try {
                Future future =list.get(i);
                System.out.println(future.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
        executors.shutdown();
        //下面代码会报异常，shutdown后拒绝提交任务
//        executors.submit(new InnerA(555));

    }

    private class InnerA implements Callable{
        private Integer a;
        public InnerA(Integer a){
            this.a = a;
        }
        @Override
        public Object call() throws Exception {
            User user = new User();
            user.setAge(a);
            System.out.println("id="+a+"先到达");
            Thread.sleep(5000);
            return user;
        }
    }
}
